using System;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using RedRiver.Framework.XtraCommon.Templates;

namespace RedRiver.Framework.XtraCommon.FormHelper.TypeSelection {
    public partial class TypeSelectorUI : XtraDialogForm {
        private TextBox _typeInfoCtl;

        private TypeSelectorUI() {
            _openFileDialog = new OpenFileDialog();
            InitializeComponent();
            _openFileDialog.Filter = AssemblyFileFilter;
            _openFileDialog.DereferenceLinks = false;
            _openFileDialog.FileName = Application.StartupPath;
        }

        public TypeSelectorUI(Type currentType, Type baseType, TypeAttributes flags)
            : this() {
            _selector = new TypeSelector(currentType, baseType, flags);
            TypeSelector.InitTreeView(_treeView);
            _treeView.Select();
        }

        public TypeSelectorUI(TypeFilter filter, object filterCriteria) : this() {
            _selector = new TypeSelector(filter, filterCriteria);
            TypeSelector.InitTreeView(_treeView);
            _treeView.Select();
        }

        public TypeSelectorUI(TypeSelector selector) : this() {
            _selector = selector;
            TypeSelector.InitTreeView(_treeView);
        }

        public Type SelectedType {
            get { return (_treeView.SelectedNode.Tag as Type); }
        }

        public ImageList TypeImageList {
            get { return _typeImageList; }
        }

        private void DisplayMessageBox(string message, string caption) {
            MessageBoxOptions options = 0;
            if (RightToLeft == RightToLeft.Yes) {
                options = MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign;
            }
            MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Asterisk,
                            MessageBoxDefaultButton.Button1, options);
        }

        private void OnBrowseButtonClick(object sender, EventArgs e) {
            if (_openFileDialog.ShowDialog() == DialogResult.OK) {
                try {
                    Assembly assembly = Assembly.LoadFrom(_openFileDialog.FileName);
                    if (!TypeSelector.LoadTreeView(assembly)) {
                        DisplayMessageBox(
                            string.Format(CultureInfo.CurrentUICulture,
                                          Resources.NoTypesFoundInAssemblyErrorMessage,
                                          new object[] {assembly.GetName().Name, TypeSelector.TypeToVerify.FullName}),
                            Resources.NoTypesFoundInAssemblyCaption);
                    }
                } catch (FileNotFoundException exception) {
                    DisplayMessageBox(
                        string.Format(CultureInfo.CurrentUICulture, Resources.AssemblyLoadFailedErrorMessage,
                                      new object[] {exception.Message}), string.Empty);
                } catch (BadImageFormatException exception2) {
                    DisplayMessageBox(
                        string.Format(CultureInfo.CurrentUICulture, Resources.AssemblyLoadFailedErrorMessage,
                                      new object[] {exception2.Message}), string.Empty);
                }
            }
        }

        private void OnTreeViewDoubleClick(object sender, EventArgs e) {
            if (SelectedType != null) {
                DialogResult = DialogResult.OK;
                Close();
            }
        }

        private void _treeView_AfterSelect(object sender, TreeViewEventArgs e) {
            Text = FormTitle + e.Node.Text;

            if (e.Node.Nodes.Count > 0) {
                e.Node.Expand();
            }
            if (e.Node.Tag is Type) {
                ShowTypeInfo((Type) e.Node.Tag);
            }
        }

        private void ShowTypeInfo(Type t) {
            if (_typeInfoCtl == null) {
                _typeInfoCtl = new TextBox {
                                               Multiline = true,
                                               ReadOnly = true,
                                               BorderStyle = BorderStyle.FixedSingle,
                                               BackColor = SystemColors.Info,
                                               Dock = DockStyle.Bottom,
                                               Width = _treeView.Width,
                                               Height = _treeView.Height/4,
                                               AcceptsReturn = true
                                           };
                _treeView.Controls.Add(new Splitter {Dock = DockStyle.Bottom});
                _treeView.Controls.Add(_typeInfoCtl);
            }
            _typeInfoCtl.Text = string.Format("{0}\n{1}", GetTypeInfo(t), t.Assembly.FullName);
        }

        private static string GetTypeInfo(Type t) {
            string info = string.Empty;
            if (t.IsPublic) {
                info = "Public ";
            }
            if (t.IsClass) {
                info += "Class ";
            } else if (t.IsInterface) {
                info += "Interface ";
            } else if (t.IsEnum) {
                info += "enum ";
            }
            info += t.Name;
            if (t.BaseType != typeof (object)) {
                info += ":" + t.BaseType.Name;
            }
            Type[] interfaces = t.GetInterfaces();
            if (interfaces.Length > 0) {
                foreach (Type @interface in interfaces) {
                    info += @interface.Name + ",";
                }
            }
            return info;
        }
    }
}